package com.zhaofujun.filequeue;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

/**
 * Kryo序列化工具类（适用于Java 8）
 * 注意：Kryo实例非线程安全，通过ThreadLocal确保线程隔离
 */
public class KryoSerializerV2<T> implements Serializer<T> {

    private final Class<T> clazz;

    // 线程局部变量：每个线程持有一个Kryo实例
    private final ThreadLocal<Kryo> KRYO_THREAD_LOCAL = new ThreadLocal<Kryo>() {
        @Override
        protected Kryo initialValue() {
            Kryo kryo = new Kryo();
            // 配置：关闭默认的类注册验证（提升性能，Java 8中无需严格验证）
            kryo.setRegistrationRequired(false);
            kryo.register(clazz);
            return kryo;
        }
    };

    public KryoSerializerV2(Class<T> clazz) {
        this.clazz = clazz;
    }

    /**
     * 序列化：将对象转换为字节数组
     *
     * @param obj 待序列化的对象（不能为null）
     * @return 序列化后的字节数组
     */
    public byte[] serialize(Object obj) {
        if (obj == null) {
            throw new IllegalArgumentException("序列化对象不能为null");
        }

        // 使用Kryo的Output流写入字节
        try (ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
             Output output = new Output(byteOut)) {
            // 获取当前线程的Kryo实例
            Kryo kryo = KRYO_THREAD_LOCAL.get();
            // 写入对象（自动处理类型信息）
            kryo.writeObject(output, obj);
            output.flush();
            return byteOut.toByteArray();
        } catch (Exception e) {
            throw new RuntimeException("Kryo序列化失败", e);
        }
    }

    /**
     * 反序列化：将字节数组转换为对象
     *
     * @param data 序列化后的字节数组（不能为null或空）
     * @return 反序列化后的对象
     */
    @Override
    public T deserialize(byte[] data) {
        if (data == null || data.length == 0) {
            throw new IllegalArgumentException("反序列化字节数组不能为null或空");
        }
        if (clazz == null) {
            throw new IllegalArgumentException("目标类不能为null");
        }

        // 使用Kryo的Input流读取字节
        try (ByteArrayInputStream byteIn = new ByteArrayInputStream(data);
             Input input = new Input(byteIn)) {
            // 获取当前线程的Kryo实例
            Kryo kryo = KRYO_THREAD_LOCAL.get();
            // 读取对象（指定目标类）
            return kryo.readObject(input, clazz);
        } catch (Exception e) {
            throw new RuntimeException("Kryo反序列化失败", e);
        }
    }


    // 测试用的POJO类
    static class User {
        private Long id;
        private String name;
        private int age;
        private String email;

        // 必须有默认构造函数（Kryo反序列化需要）
        public User() {
        }

        public User(Long id, String name, int age, String email) {
            this.id = id;
            this.name = name;
            this.age = age;
            this.email = email;
        }

        @Override
        public String toString() {
            return "User{id=" + id + ", name='" + name + "', age=" + age + ", email='" + email + "'}";
        }

        // getter和setter（可选，Kryo可直接访问字段）
        public Long getId() {
            return id;
        }

        public String getName() {
            return name;
        }

        public int getAge() {
            return age;
        }

        public String getEmail() {
            return email;
        }
    }
}
